﻿#region License
// Copyright 2010 Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#endregion

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Permissions;
using System.Diagnostics;

namespace MediaWiki.MediaWikiConverter.Utilities.Logging.Writers
{
  public class TraceWriter : LogWriterBase
  {
    private static readonly object _lock = new object();

    private static TraceEventType GetTraceEventType(LogLevel logLevel)
    {
      switch (logLevel)
      {
        case LogLevel.Critical:
          return TraceEventType.Critical;
        case LogLevel.Error:
          return TraceEventType.Error;
        case LogLevel.Warning:
          return TraceEventType.Warning;
        case LogLevel.Information:
          return TraceEventType.Information;
        case LogLevel.Verbose:
          return TraceEventType.Verbose;
        default:
          throw new ArgumentOutOfRangeException("logLevel");
      }
    }

    public override void Write(LogEntry logEntry)
    {
      TraceEvent(GetTraceEventType(logEntry.LogLevel), 0, FormatMessage(logEntry));
    }

    private static string _appName;

    internal static string AppName
    {
      get
      {
        if (_appName == null)
        {
          new EnvironmentPermission(EnvironmentPermissionAccess.Read, "Path").Assert();
          _appName = Path.GetFileName(Environment.GetCommandLineArgs()[0]);
        }

        return _appName;
      }
    }

    public static void TraceEvent(TraceEventType eventType, int id, string format, params object[] args)
    {
      // todo: copied from .NET. Need to clean up
      TraceEventCache eventCache = new TraceEventCache();

      if (Trace.UseGlobalLock)
      {
        lock (_lock)
        {
          if (args == null)
          {
            foreach (TraceListener listener in Trace.Listeners)
            {
              listener.TraceEvent(eventCache, AppName, eventType, id, format);
              if (Trace.AutoFlush)
              {
                listener.Flush();
              }
            }
          }
          else
          {
            foreach (TraceListener listener2 in Trace.Listeners)
            {
              listener2.TraceEvent(eventCache, AppName, eventType, id, format, args);
              if (Trace.AutoFlush)
              {
                listener2.Flush();
              }
            }
          }
        }
      }
      else
      {
        if (args == null)
        {
          foreach (TraceListener listener3 in Trace.Listeners)
          {
            if (!listener3.IsThreadSafe)
            {
              lock (listener3)
              {
                listener3.TraceEvent(eventCache, AppName, eventType, id, format);
                if (Trace.AutoFlush)
                {
                  listener3.Flush();
                }
                continue;
              }
            }
            listener3.TraceEvent(eventCache, AppName, eventType, id, format);
            if (Trace.AutoFlush)
            {
              listener3.Flush();
            }
          }
        }
        else
        {
          foreach (TraceListener listener4 in Trace.Listeners)
          {
            if (!listener4.IsThreadSafe)
            {
              lock (listener4)
              {
                listener4.TraceEvent(eventCache, AppName, eventType, id, format, args);
                if (Trace.AutoFlush)
                {
                  listener4.Flush();
                }
                continue;
              }
            }
            listener4.TraceEvent(eventCache, AppName, eventType, id, format, args);
            if (Trace.AutoFlush)
            {
              listener4.Flush();
            }
          }
        }
      }
    }
  }
}